/**
 * Agent Configuration API Routes
 * 
 * RESTful API for managing agent configurations
 */

import { Hono } from 'hono';
import { z } from 'zod';
import { agentConfigManager } from '../../agent-designer/agent-config-manager';
import type {
  CreateAgentRequest,
  UpdateAgentRequest,
} from '../../types/agent-config';

const app = new Hono();

// Validation schemas
const systemPromptSchema = z.object({
  type: z.enum(['text', 'preset']),
  content: z.string(),
  preset: z.string().optional(),
});

const toolConfigSchema = z.object({
  name: z.string(),
  enabled: z.boolean(),
  config: z.record(z.any()).optional(),
});

const subagentConfigSchema = z.object({
  id: z.string(),
  name: z.string(),
  description: z.string(),
  enabled: z.boolean(),
});

const nodePositionSchema = z.object({
  x: z.number(),
  y: z.number(),
});

const workflowNodeSchema = z.object({
  id: z.string(),
  type: z.enum(['input', 'processing', 'tool_call', 'subagent', 'condition', 'loop', 'output']),
  position: nodePositionSchema,
  data: z.object({
    label: z.string(),
    description: z.string().optional(),
    config: z.record(z.any()).optional(),
  }),
});

const workflowEdgeSchema = z.object({
  id: z.string(),
  source: z.string(),
  target: z.string(),
  label: z.string().optional(),
  condition: z.string().optional(),
});

const agentSettingsSchema = z.object({
  maxTokens: z.number().optional(),
  temperature: z.number().optional(),
  contextStrategy: z.enum(['compact', 'full', 'custom']),
  maxTurns: z.number().optional(),
  includePartialMessages: z.boolean().optional(),
});

const createAgentSchema = z.object({
  name: z.string().min(1).max(100),
  description: z.string().max(500),
  systemPrompt: systemPromptSchema,
  model: z.enum(['claude-opus-4', 'claude-sonnet-4', 'claude-sonnet-4.5', 'claude-haiku-4']),
  tools: z.array(toolConfigSchema).optional(),
  subagents: z.array(subagentConfigSchema).optional(),
  workflow: z.object({
    nodes: z.array(workflowNodeSchema),
    edges: z.array(workflowEdgeSchema),
  }).optional(),
  settings: agentSettingsSchema.partial().optional(),
});

const updateAgentSchema = createAgentSchema.partial();

/**
 * GET /api/agents
 * List all agent configurations
 */
app.get('/', async (c) => {
  try {
    const page = parseInt(c.req.query('page') || '1');
    const pageSize = parseInt(c.req.query('pageSize') || '20');

    const result = await agentConfigManager.listAgents(page, pageSize);
    return c.json(result);
  } catch (error) {
    console.error('Error listing agents:', error);
    return c.json({ error: 'Failed to list agents' }, 500);
  }
});

/**
 * GET /api/agents/:id
 * Get a specific agent configuration
 */
app.get('/:id', async (c) => {
  try {
    const id = c.req.param('id');
    const agent = await agentConfigManager.getAgent(id);

    if (!agent) {
      return c.json({ error: 'Agent not found' }, 404);
    }

    return c.json(agent);
  } catch (error) {
    console.error('Error getting agent:', error);
    return c.json({ error: 'Failed to get agent' }, 500);
  }
});

/**
 * POST /api/agents
 * Create a new agent configuration
 */
app.post('/', async (c) => {
  try {
    const body = await c.req.json();
    const validated = createAgentSchema.parse(body);

    const agent = await agentConfigManager.createAgent(validated as CreateAgentRequest);
    return c.json(agent, 201);
  } catch (error) {
    console.error('Error creating agent:', error);
    if (error instanceof z.ZodError) {
      return c.json({ error: 'Validation error', details: error.errors }, 400);
    }
    return c.json({ error: 'Failed to create agent' }, 500);
  }
});

/**
 * PUT /api/agents/:id
 * Update an agent configuration
 */
app.put('/:id', async (c) => {
  try {
    const id = c.req.param('id');
    const body = await c.req.json();
    const validated = updateAgentSchema.parse(body);

    const agent = await agentConfigManager.updateAgent(id, validated as UpdateAgentRequest);
    return c.json(agent);
  } catch (error) {
    console.error('Error updating agent:', error);
    if (error instanceof z.ZodError) {
      return c.json({ error: 'Validation error', details: error.errors }, 400);
    }
    if (error instanceof Error && error.message.includes('not found')) {
      return c.json({ error: 'Agent not found' }, 404);
    }
    return c.json({ error: 'Failed to update agent' }, 500);
  }
});

/**
 * DELETE /api/agents/:id
 * Delete an agent configuration
 */
app.delete('/:id', async (c) => {
  try {
    const id = c.req.param('id');
    const deleted = await agentConfigManager.deleteAgent(id);

    if (!deleted) {
      return c.json({ error: 'Agent not found' }, 404);
    }

    return c.json({ success: true });
  } catch (error) {
    console.error('Error deleting agent:', error);
    return c.json({ error: 'Failed to delete agent' }, 500);
  }
});

/**
 * POST /api/agents/:id/duplicate
 * Duplicate an agent configuration
 */
app.post('/:id/duplicate', async (c) => {
  try {
    const id = c.req.param('id');
    const body = await c.req.json().catch(() => ({}));
    const newName = body.name;

    const agent = await agentConfigManager.duplicateAgent(id, newName);
    return c.json(agent, 201);
  } catch (error) {
    console.error('Error duplicating agent:', error);
    if (error instanceof Error && error.message.includes('not found')) {
      return c.json({ error: 'Agent not found' }, 404);
    }
    return c.json({ error: 'Failed to duplicate agent' }, 500);
  }
});

/**
 * POST /api/agents/:id/validate
 * Validate an agent's workflow
 */
app.post('/:id/validate', async (c) => {
  try {
    const id = c.req.param('id');
    const agent = await agentConfigManager.getAgent(id);

    if (!agent) {
      return c.json({ error: 'Agent not found' }, 404);
    }

    const validation = agentConfigManager.validateWorkflow(agent.workflow);
    return c.json(validation);
  } catch (error) {
    console.error('Error validating agent:', error);
    return c.json({ error: 'Failed to validate agent' }, 500);
  }
});

/**
 * GET /api/agents/templates
 * Get all agent templates
 */
app.get('/templates/list', async (c) => {
  try {
    const templates = await agentConfigManager.getTemplates();
    return c.json({ templates });
  } catch (error) {
    console.error('Error getting templates:', error);
    return c.json({ error: 'Failed to get templates' }, 500);
  }
});

/**
 * POST /api/agents/templates/:templateId
 * Create an agent from a template
 */
app.post('/templates/:templateId', async (c) => {
  try {
    const templateId = c.req.param('templateId');
    const body = await c.req.json().catch(() => ({}));
    const name = body.name;

    const agent = await agentConfigManager.createFromTemplate(templateId, name);
    return c.json(agent, 201);
  } catch (error) {
    console.error('Error creating agent from template:', error);
    if (error instanceof Error && error.message.includes('not found')) {
      return c.json({ error: 'Template not found' }, 404);
    }
    return c.json({ error: 'Failed to create agent from template' }, 500);
  }
});

export default app;

